﻿using System.Runtime.InteropServices;

namespace System
{
	public partial class ProcessMemory
	{
		public int Handle = 0;

		public void OpenProcess()
		{
			uint access = (uint)(ProcessAccessType.PROCESS_VM_READ | ProcessAccessType.PROCESS_VM_WRITE | ProcessAccessType.PROCESS_VM_OPERATION);
			System.Diagnostics.Process.EnterDebugMode();
			Handle = OpenProcess(access, 1, P.Id);

			Console.WriteLine("Process opened with handle " + Handle);
			//SetError();
		}
		public void CloseProcess()
		{
			if (CloseHandle(Handle) != 0)
				throw new Exception("Close error");
		}

		byte[] Buffer;
		public int Res;
		public int Error;
		void SetError()
		{
			Error = Marshal.GetLastWin32Error();
			Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
		}
		void Read(int Address, int Length)
		{
			//Console.WriteLine("start reading at " + Address);
			Buffer = new byte[Length];
			//Console.WriteLine("read...");
			ReadProcessMemory(Handle, Address, Buffer, Length, out Res);
			//Console.WriteLine("read " + Res + " bytes");
			//SetError();
		}
		public byte[] ReadBytes(int Address, int Length)
		{
			Read(Address, Length);
			return Buffer;
		}
		public short ReadInt16(int A)
		{
			Read(A, 2);
			return BitConverter.ToInt16(Buffer, 0);
		}
		public ushort ReadUInt16(int A)
		{
			Read(A, 2);
			return BitConverter.ToUInt16(Buffer, 0);
		}
		public int ReadInt32(int A)
		{
			Read(A, 4);
			return BitConverter.ToInt32(Buffer, 0);
		}
		public long ReadInt64(int A)
		{
			Read(A, 8);
			return BitConverter.ToInt64(Buffer, 0);
		}
		public float ReadSingle(int A)
		{
			Read(A, 4);
			return BitConverter.ToSingle(Buffer, 0);
		}
		public double ReadDouble(int A)
		{
			Read(A, 8);
			return BitConverter.ToDouble(Buffer, 0);
		}
		public String ReadString(int A)
		{
			Read(A, 1);
			String Res = "";
			while (Buffer[0] != 0)
			{
				A++;
				Res += "" + (char)Buffer[0];
				Read(A, 1);
			}
			return Res;
		}
		public void WriteByte(int A, byte value)
		{
			WriteProcessMemory(Handle, A, new byte[] { value }, 1, out Res);
		}
		public void WriteInt16(int A, short value)
		{
			byte[] buf = BitConverter.GetBytes(value);
			WriteProcessMemory(Handle, A, buf, 2, out Res);
		}
		public void WriteUInt16(int A, ushort value)
		{
			byte[] buf = BitConverter.GetBytes(value);
			WriteProcessMemory(Handle, A, buf, 2, out Res);
		}
		public void WriteInt32(int A, int value)
		{
			byte[] buf = BitConverter.GetBytes(value);
			WriteProcessMemory(Handle, A, buf, 4, out Res);
		}
		public void WriteSingle(int A, float value)
		{
			byte[] buf = BitConverter.GetBytes(value);
			WriteProcessMemory(Handle, A, buf, 4, out Res);
		}
		public void WriteDouble(int A, double value)
		{
			byte[] buf = BitConverter.GetBytes(value);
			WriteProcessMemory(Handle, A, buf, 8, out Res);
		}
	}
}